using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using RandomGen;
using 地图哇哇哇.地图;

namespace Numbers
{
    public static class Random
    {
        public static double Range(double min, double max)
        {
            if (max <= min)
            {
                throw new  ArgumentOutOfRangeException($"参数max必须大于min，请检查参数！");
            }
            var ran = new System.Random();
            return ran.NextDouble() % (max - min) + min;
        }
    }
}

namespace 地图哇哇哇
{
    public class Datar
    {
        public static long 出图耗时 = 0;

        /// <summary>
        /// 微软雅黑
        /// </summary>
        public static GlyphTypeface Simhei => new GlyphTypeface(new Uri(Environment.GetFolderPath(Environment.SpecialFolder.Fonts) + "\\simhei.ttf", UriKind.Absolute));

        public static 测试层 生成随机测试层(Size 容器尺寸, int 区域数下限, int 区域数上限)
        {
            var sw = new Stopwatch();
            sw.Start();
            var bian = Gen.Random.Numbers.Integers(2, 5).Invoke();
            var 块 = new 基块 {尺寸 = new Size(bian, bian)};
            var c = new 测试层
            {
                编号 = $"csc-{Guid.NewGuid().ToString()}",
                尺寸 = 基块.获取容器尺寸(容器尺寸, 块),
                名称 = $"测试层啊！", 显示层格线 = true,
                填充画笔 = new SolidColorBrush(ColorGenerator.GetColor(10)),
            };
            var 区域数 = new System.Random().Next(区域数下限, 区域数上限);

            void 计算区域的尺寸和位置(out int a, out int b, out int x, out int y)
            {
                a = Gen.Random.Numbers.Integers(100, c.尺寸.横长 / 2 > 100 ? c.尺寸.横长 / 2 : c.尺寸.横长).Invoke();
                b = Gen.Random.Numbers.Integers(100, c.尺寸.纵长 / 2 > 100 ? c.尺寸.纵长 / 2 : c.尺寸.纵长).Invoke();
                x = Gen.Random.Numbers.Integers(0, c.尺寸.横长 - a).Invoke();
                y = Gen.Random.Numbers.Integers(0, c.尺寸.纵长 - b).Invoke();
            }

            //确定第一个区域的大小和位置
            计算区域的尺寸和位置(out var a1, out var b1, out var x1, out var y1);
            var 第一区域 = new 测试区域
            {
                位置 = new 地图位置 {横坐标 = x1, 纵坐标 = y1, 格长度 = c.尺寸.格长度},
                尺寸 = new 地图尺寸 {格长度 = c.尺寸.格长度, 横长 = a1, 纵长 = b1},
                编号 = Guid.NewGuid().ToString(),
                名称 = "第1区域",
                填充画笔 = Brushes.Black,
                显示文字 = true,
                基块们 = new 基块[a1, b1]
            };
            第一区域.随机地形();
            for (int j = 0; j < 区域数 - 1; j++)
            {
                计算区域的尺寸和位置(out var a, out var b, out var xa, out var ya);
                var q = new 测试区域
                {
                    显示文字 = true,
                    基块们 = new 基块[a, b],
                    位置 = new 地图位置 {横坐标 = xa, 纵坐标 = ya, 格长度 = c.尺寸.格长度},
                    尺寸 = new 地图尺寸 {横长 = a, 纵长 = b, 格长度 = c.尺寸.格长度}, 填充画笔 = Brushes.Black,
                    边框画笔 = new SolidColorBrush(ColorGenerator.GetColor(100)),
                    名称 = Gen.Random.Names.Full().Invoke()
                };
                q.随机地形();
                c.测试区域们.Add(q);
            }

            c.测试区域们.Add(第一区域);
            sw.Stop();
            c.生成耗时 = sw.ElapsedMilliseconds;
            return c;
        }

        public static 生成国家测试的结果 生成一些随机帝国(byte 最少帝国数, byte 最大帝国数, byte 最少王国数, byte 最大王国数, byte 最少府数, byte 最大府数, byte 最少州数, byte 最大州数, byte 最少郡数, byte 最大郡数, byte 最少县数, byte 最大县数, byte 最少镇数, byte 最大镇数, byte 最少乡数, byte 最大乡数, byte 最少村数, ushort 最大村数)
        {
            var sw = new Stopwatch();
            sw.Start();

            ObservableCollection<州> 生成州()
            {
                var 州数 = Gen.Random.Numbers.Bytes(最少州数, 最大州数).Invoke();
                var 州s = new ObservableCollection<州>();
                for (var k = 0; k < 州数; k++)
                {
                    var 州 = new 州 {郡们 = new ObservableCollection<郡>()};
                    州.名称 = Gen.Random.Names.Full().Invoke();
                    州s.Add(州);
                    var 郡数 = Gen.Random.Numbers.Bytes(最少郡数, 最大郡数).Invoke();
                    for (var l = 0; l < 郡数; l++)
                    {
                        var 郡 = new 郡 {县们 = new ObservableCollection<县>(), 名称 = Gen.Random.Names.Full().Invoke()};
                        州.郡们.Add(郡);
                        var 县数 = Gen.Random.Numbers.Bytes(最少县数, 最大县数).Invoke();
                        for (var m = 0; m < 县数; m++)
                        {
                            var 县 = new 县 {镇们 = new ObservableCollection<镇>(), 乡们 = new ObservableCollection<乡>(), 名称 = Gen.Random.Names.Full().Invoke()};
                            郡.县们.Add(县);
                            var 县区人口 = new 人口 {口数 = (ulong) Gen.Random.Numbers.Longs(30000, 500000).Invoke(), 年死亡率 = Numbers.Random.Range(0.004f, 0.04f), 年出生率 = Numbers.Random.Range(0.004f, 0.04f), 男性比率 = Numbers.Random.Range(0.38f, 0.58f)};
                            var 县区生灵 = new 生灵 {其它生灵数 = (ulong) Gen.Random.Numbers.Longs(3_0000_0000_0000, 30_0000_0000_0000).Invoke(), 禽数 = (ulong) Gen.Random.Numbers.Longs(3000, 3_0000).Invoke(), 兽数 = (ulong) Gen.Random.Numbers.Longs(300, 15000).Invoke(), 人口 = 县区人口};
                            县.生灵 = 县区生灵;
                            var 镇数 = Gen.Random.Numbers.Bytes(最少镇数, 最大镇数).Invoke();
                            var 乡数 = Gen.Random.Numbers.Bytes(最少乡数, 最大乡数).Invoke();
                            for (var n = 0; n < 镇数; n++)
                            {
                                var 镇 = new 镇 {名称 = Gen.Random.Names.Full().Invoke()};
                                var 镇区人口 = new 人口 {口数 = (ulong) Gen.Random.Numbers.Longs(10000, 50000).Invoke(), 年死亡率 = Numbers.Random.Range(0.005f, 0.05f), 年出生率 = Numbers.Random.Range(0.005f, 0.05f), 男性比率 = Numbers.Random.Range(0.4f, 0.6f)};
                                var 镇区生灵 = new 生灵 {其它生灵数 = (ulong) Gen.Random.Numbers.Longs(1_0000_0000_0000, 10_0000_0000_0000).Invoke(), 禽数 = (ulong) Gen.Random.Numbers.Longs(1000, 1_0000).Invoke(), 兽数 = (ulong) Gen.Random.Numbers.Longs(100, 5000).Invoke(), 人口 = 镇区人口};
                                镇.生灵 = 镇区生灵;
                                镇.村们 = new ObservableCollection<村>();
                                var 村数 = Gen.Random.Numbers.UnsignedIntegers(最少村数, 最大村数).Invoke();
                                double a = 0, b = 0;
                                ulong c = 0;
                                for (var o = 0; o < 村数; o++)
                                {
                                    var 村 = new 村 {名称 = Gen.Random.Names.Full().Invoke()};
                                    var 村人口 = new 人口 {口数 = (ulong) Gen.Random.Numbers.Longs(100, 10000).Invoke(), 年死亡率 = Numbers.Random.Range(0.01f, 0.1f), 年出生率 = Numbers.Random.Range(0.01f, 0.1f), 男性比率 = Numbers.Random.Range(0.45f, 0.7f)};
                                    村.生灵 = new 生灵 {其它生灵数 = (ulong) Gen.Random.Numbers.Longs(10_0000_0000_0000, 100_0000_0000_0000).Invoke(), 禽数 = (ulong) Gen.Random.Numbers.Longs(100, 100_0000).Invoke(), 兽数 = (ulong) Gen.Random.Numbers.Longs(10, 1000).Invoke(), 人口 = 村人口};
                                    镇.村们.Add(村);
                                    镇.生灵.兽数 += 村.生灵.兽数;
                                    镇.生灵.禽数 += 村.生灵.禽数;
                                    镇.生灵.其它生灵数 += 村.生灵.其它生灵数;
                                    镇.生灵.人口.口数 += 村人口.口数;
                                    a += 村人口.年出生率;
                                    b += 村人口.年死亡率;
                                    c += 村人口.男性数量;
                                }

                                镇.生灵.人口.年出生率 = (a + 镇.生灵.人口.年出生率) / (村数 + 1);
                                镇.生灵.人口.年死亡率 = (b + 镇.生灵.人口.年死亡率) / (村数 + 1);
                                镇.生灵.人口.男性比率 = (c + 镇.生灵.人口.男性数量) / (double) 镇.生灵.人口.口数;
                                县.镇们.Add(镇);
                                县.生灵.兽数 += 镇.生灵.兽数;
                                县.生灵.禽数 += 镇.生灵.禽数;
                                县.生灵.其它生灵数 += 镇.生灵.其它生灵数;
                                县.生灵.人口.口数 += 镇.生灵.人口.口数;
                            }

                            for (var n = 0; n < 乡数; n++)
                            {
                                var 乡 = new 乡 {生灵 = new 生灵 {人口 = new 人口()}, 村们 = new ObservableCollection<村>(), 名称 = Gen.Random.Names.Full().Invoke()};
                                var 村数 = Gen.Random.Numbers.UnsignedIntegers(最少村数, 最大村数).Invoke();
                                double a = 0, b = 0;
                                ulong c = 0;
                                for (var o = 0; o < 村数; o++)
                                {
                                    var 村 = new 村 {名称 = Gen.Random.Names.Full().Invoke()};
                                    var 村人口 = new 人口 {口数 = (ulong) Gen.Random.Numbers.Longs(100, 10000).Invoke(), 年死亡率 = Numbers.Random.Range(0.01f, 0.1f), 年出生率 = Numbers.Random.Range(0.01f, 0.1f), 男性比率 = Numbers.Random.Range(0.45f, 0.7f)};
                                    村.生灵 = new 生灵 {其它生灵数 = (ulong) Gen.Random.Numbers.Longs(10_0000_0000_0000, 100_0000_0000_0000).Invoke(), 禽数 = (ulong) Gen.Random.Numbers.Longs(100, 100_0000).Invoke(), 兽数 = (ulong) Gen.Random.Numbers.Longs(10, 1000).Invoke(), 人口 = 村人口};
                                    乡.村们.Add(村);
                                    乡.生灵.兽数 += 村.生灵.兽数;
                                    乡.生灵.禽数 += 村.生灵.禽数;
                                    乡.生灵.其它生灵数 += 村.生灵.其它生灵数;
                                    乡.生灵.人口.口数 += 村人口.口数;
                                    a += 村人口.年出生率;
                                    b += 村人口.年死亡率;
                                    c += 村人口.男性数量;
                                }

                                乡.生灵.人口.年出生率 = a / 村数;
                                乡.生灵.人口.年死亡率 = b / 村数;
                                乡.生灵.人口.男性比率 = c / (double) 乡.生灵.人口.口数;
                                县.乡们.Add(乡);
                            }
                        }
                    }
                }

                return 州s;
            }

            var re = new 生成国家测试的结果{所有帝国=new ObservableCollection<帝国>()};
            var 帝国数 = Gen.Random.Numbers.Bytes(最少帝国数, 最大帝国数).Invoke();
            Parallel.For(0, 帝国数, act =>
            {
                var 帝国 = new 帝国 {王国们 = new ObservableCollection<王国>(), 府们 = new ObservableCollection<府>()};
                re.所有帝国.Add(帝国);
                var 王国数 = Gen.Random.Numbers.Bytes(最少王国数, 最大王国数).Invoke();
                Parallel.For(0, 王国数, a =>
                {
                    var 王国 = new 王国 {州们 = 生成州(),名称=Gen.Random.Countries().Invoke()};
                    帝国.王国们.Add(王国);
                });
                var 府数 = Gen.Random.Numbers.Bytes(最少府数, 最大府数).Invoke();
                Parallel.For(0, 府数, a =>
                {
                    var 府 = new 府 {州们 = 生成州(),名称=Gen.Random.Countries().Invoke()};
                    帝国.府们.Add(府);
                });
            });
            sw.Stop();
            re.生成耗时 = sw.ElapsedMilliseconds;
            return re;
        }
    }
}